﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RPGXEngine.Scripting.SystemFunctions;

namespace RPGXEngine
{
    public class Function
    {
        #region Properties

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        private string _name = String.Empty;

        public DataType ReturnType { get; set; }

        public List<IVariableType> Arguments
        {
            get { return _arguments; }
            private set { _arguments = value; }
        }
        private List<IVariableType> _arguments = new List<IVariableType>();

        public List<ICommand> Commands
        {
            get { return _commands; }
            set { _commands = value; }
        }
        private List<ICommand> _commands = new List<ICommand>();

        public List<string> BodyParts
        {
            get { return _bodyParts; }
            set { _bodyParts = value; }
        }
        private List<string> _bodyParts = new List<string>();

        public FunctionScope Scope
        {
            get { return _scope; }
            set { _scope = value; }
        }
        private FunctionScope _scope = new FunctionScope();

        public bool IsSystemFunction
        {
            get { return _isSystemFunction; }
            set { _isSystemFunction = value; }
        }
        private bool _isSystemFunction = false;

        public SystemFunction.SystemFunctionDelegate SystemFunction
        {
            get { return _systemFunction; }
            set { _systemFunction = value; }
        }
        private SystemFunction.SystemFunctionDelegate _systemFunction = null;

        #endregion

        #region Public Methods

        public IVariableType Execute(ScriptManager sm)
        {
            IVariableType vt = null;

            if (this.IsSystemFunction)
            {
                if (this.SystemFunction != null)
                {
                    vt = this.SystemFunction(sm, this.Scope, this.Scope.Arguments);
                }
            }
            else
            {
                foreach (var cmd in this.Commands)
                {
                    if (cmd.IsReturn)
                    {
                        vt = cmd.Execute(sm, this.Scope);
                        break;
                    }
                    else
                    {
                        cmd.Execute(sm, this.Scope);
                    }
                }
            }

            // got to the end of the method or no return statment
            if (vt == null)
            {
                switch (this.ReturnType)
                {
                    case DataType.Void:
                        vt = new VoidVariableType(String.Empty);
                        break;
                    case DataType.Var:
                        vt = new VarVariableType(String.Empty);
                        break;
                    case DataType.Array:
                        vt = new ArrayVariableType(String.Empty);
                        break;
                    default:
                        vt = new VarVariableType(String.Empty);
                        break;
                }
            }

            return vt; // this will return the 'return' commands return value -- vt = the return value of the 'return' command whereever that may be in the list of commands above
        }

        #endregion
    }
}
